package com.binarycat.dynamiclimit.util;

import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.binarycat.dynamiclimit.DynamicLimiterManager;
import com.binarycat.dynamiclimit.bean.DynamicLimitData;
import com.binarycat.dynamiclimit.bean.DynamicLimiterConfig;
import com.binarycat.dynamiclimit.bean.MethodMappingLimitData;
import com.binarycat.dynamiclimit.constant.CommonLimitConstants;
import com.binarycat.dynamiclimit.metric.SlidingHistory;
import com.binarycat.util.jvm.SystemInfoUtils;
import com.codahale.metrics.Meter;
import com.codahale.metrics.Metric;
import com.codahale.metrics.MetricRegistry;

/**
 * 限流日志工具类
 * 
 * @author jjb
 * @date 2018/08/16
 */
public class LimitRateLogUtils {

    private final static Logger logger = LoggerFactory.getLogger(LimitRateLogUtils.class);
    // private final static File file = new File("/Users/jjb/Downloads/data/log.txt");
    /**
     * 日志记录开关
     */
    private static boolean logswitch = false;

    /**
     * 打印度量信息
     * 
     * @param dynamicLimiterManager
     */
    public static void showMetricInfo(DynamicLimiterManager dynamicLimiterManager) {
        if (!logswitch) {
            return;
        }

        double jvmProcessCpuLoad = SystemInfoUtils.getJvmProcessCpuLoad();
        double jvmMemoryUsageRate = SystemInfoUtils.getJvmMemoryUsageRate();
        DynamicLimitData limitData = dynamicLimiterManager.getLimitData();
        DynamicLimiterConfig config = dynamicLimiterManager.getDynamicLimiterConfig();
        Map<String, MethodMappingLimitData> methodMappingLimitDataMap = limitData.getMethodMappingLimitDataMap();
        Map<String, Metric> metricMap = limitData.getMetricRegistry().getMetrics();

        log("**********************************************************************");
        log("cpu负载:" + SystemInfoUtils.getPercentage(jvmProcessCpuLoad) + "(限流阀值"
            + SystemInfoUtils.getPercentage(config.getCpuLimitRateThreshold()) + ")");

        log("内存平均使用率:" + SystemInfoUtils.getPercentage(jvmMemoryUsageRate) + "(限流阀值"
            + SystemInfoUtils.getPercentage(config.getMemoryLimitRateThreshold()) + ")");

        for (Entry<String, MethodMappingLimitData> entry : methodMappingLimitDataMap.entrySet()) {
            MethodMappingLimitData methodMappingLimitData = entry.getValue();
            Meter qpsMetric =
                (Meter)metricMap.get(MetricRegistry.name(entry.getKey(), CommonLimitConstants.METRIC_QPS));

            SlidingHistory timeOutSlidingHistory =
                (SlidingHistory)metricMap.get(MetricRegistry.name(entry.getKey(), CommonLimitConstants.METRIC_TIMEOUT));

            SlidingHistory exceptionSlidingHistory = (SlidingHistory)metricMap
                .get(MetricRegistry.name(entry.getKey(), CommonLimitConstants.METRIC_EXCEPTION));

            double rate = methodMappingLimitData.getRateLimiter().getRate();

            log("方法名".concat(entry.getKey()));
            log("一分钟内的qps:" + Math.round(qpsMetric.getOneMinuteRate()) + "(限流阀值:" + Math.round(rate) + ")");
            if (timeOutSlidingHistory != null) {
                double meanResponseTime = timeOutSlidingHistory.getDataListMean();
                log("最近1秒内请求的平均响应时间:" + (meanResponseTime) + "(限流阀值" + config.getTimeOutLimitRateThreshold() + ")");

            }
            if (exceptionSlidingHistory != null) {

                double exceptionValue = exceptionSlidingHistory.getDataListMean();
                log("最近1秒内请求的错误率:" + SystemInfoUtils.getPercentage(exceptionValue) + "(限流阀值"
                    + SystemInfoUtils.getPercentage(config.getExceptionLimitRateThreshold()) + ")");
            }
            log("");
        }
    }

    /**
     * 输出log信息
     */
    public static void log(String msg) {
        if (!logswitch) {
            return;
        }
        // logger.info(msg);
        System.out.println(msg);
        // FileUtil.appendUtf8String(msg + "\n", file);

    }

    public static boolean isLogswitch() {
        return logswitch;
    }

    public static void setLogswitch(boolean logswitch) {
        LimitRateLogUtils.logswitch = logswitch;
    }

}
